package org.bing.engine.health.task;

import java.io.IOException;
import java.util.Date;
import java.util.List;

import org.bing.engine.common.message.Message;
import org.bing.engine.common.multicast.MulticastClient;
import org.bing.engine.controller.helper.UrlBuilder;
import org.bing.engine.controller.service.LocalControllerManager;
import org.bing.engine.controller.service.LocalInstanceManager;
import org.bing.engine.core.domain.Console;
import org.bing.engine.core.domain.ContainerInstance;
import org.bing.engine.core.domain.Controller;
import org.bing.engine.core.domain.ControllerGroup;
import org.bing.engine.utility.helper.UrlHelper;

public class HeartBeatTask extends AbstractHealthTask {
    public static final String MSG_CONTROLLER_NAME = "controller.heartbeat";
    public static final String MSG_INST_NAME = "container.instance.heartbeat";
    private LocalControllerManager controllerManager;
    private LocalInstanceManager instanceManager;
    private MulticastClient client;

    public void setMulticastClient(MulticastClient client) {
        this.client = client;
    }

    public void setInstanceManager(LocalInstanceManager mgr) {
        this.instanceManager = mgr;
    }

    public void setControllerManager(LocalControllerManager mgr) {
        controllerManager = mgr;
    }

    @Override
    public void doTask() {
        // beat controller
        try {
            beatController();
        } catch (Throwable t) {
            logger.error("Fail to controller beat! " + t);
        }
        // beat container instance
        List<ContainerInstance> cinsts = instanceManager.findAllContainerInstance();
        for (ContainerInstance inst : cinsts) {
            try {
                beartContainerInstance(inst);
            } catch (Throwable t) {
                logger.error("Fail to container instance beat! " + t);
            }
        }
    }

    private void beatController() throws IOException {
        Controller controller = instanceManager.findController();
        if (controller == null) { // multicast
            client.send(controllerManager.localController());
        } else { // heart beat
            Console console = preference.getTargetConsole();
            ControllerGroup group = preference.getTargetGroup();
            controller.setGroup(group);
            sender.send(console, new Message(Message.TYPE_IN_ONLY, MSG_CONTROLLER_NAME, controller));
        }
    }

    private void beartContainerInstance(ContainerInstance instance) throws IOException {
        String state = UrlHelper.read(UrlBuilder.build(instance, "state"), 32);
        if ("OK".equalsIgnoreCase(state)) {
            Console console = preference.getTargetConsole();
            instance.setLastActivityTime(new Date());
            instance.setController(instanceManager.findController());
            sender.send(console, new Message(Message.TYPE_IN_ONLY, MSG_INST_NAME, instance));
        }
    }
}
